//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved

#include "pch.h"
#include "FMediaSinkProxy.h"
#include "FDefs.h"
#include "FMediaSink.h"

using namespace Microsoft::Media::FragmentedMediaSink;

FMediaSinkProxy::FMediaSinkProxy()
{
}

FMediaSinkProxy::~FMediaSinkProxy()
{
	AutoLock lock(_critSec);

	if (_spMediaSink != nullptr)
	{
		_spMediaSink->Shutdown();
		_spMediaSink = nullptr;
	}
}

Windows::Media::IMediaExtension ^FMediaSinkProxy::GetMFExtensions()
{
	AutoLock lock(_critSec);

	if (_spMediaSink == nullptr)
	{
		Throw(MF_E_NOT_INITIALIZED);
	}

	ComPtr<IInspectable> spInspectable;
	ThrowIfError(_spMediaSink.As(&spInspectable));

	return safe_cast<IMediaExtension^>(reinterpret_cast<Object^>(spInspectable.Get()));
}

Windows::Foundation::IAsyncOperation<IMediaExtension^>^ FMediaSinkProxy::InitializeAsync(
	Windows::Media::MediaProperties::IMediaEncodingProperties ^audioEncodingProperties,
	Windows::Media::MediaProperties::IMediaEncodingProperties ^videoEncodingProperties,
	Windows::Foundation::Collections::IVector<Microsoft::Media::FragmentedMediaSink::IFragmentController^>^ audioFragmentControllers,
	Windows::Foundation::Collections::IVector<Microsoft::Media::FragmentedMediaSink::IFragmentController^>^ videoFragmentControllers
	)
{
	return concurrency::create_async([this, videoEncodingProperties, audioEncodingProperties, videoFragmentControllers, audioFragmentControllers]()
	{
		AutoLock lock(_critSec);
		CheckShutdown();

		if (_spMediaSink != nullptr)
		{
			Throw(MF_E_ALREADY_INITIALIZED);
		}

		// Prepare the MF extension
		ThrowIfError(MakeAndInitialize<CMediaSink>(&_spMediaSink, ref new FSinkCallback(this), audioEncodingProperties, videoEncodingProperties, audioFragmentControllers, videoFragmentControllers));

		ComPtr<IInspectable> spInspectable;
		ThrowIfError(_spMediaSink.As(&spInspectable));

		return safe_cast<IMediaExtension^>(reinterpret_cast<Object^>(spInspectable.Get()));
	});
}

void FMediaSinkProxy::OnShutdown()
{
	AutoLock lock(_critSec);
	if (_fShutdown)
	{
		return;
	}
	_fShutdown = true;
	_spMediaSink = nullptr;
}

void FMediaSinkProxy::NotifyError(Exception^ ex)
{
	MediaSinkError(this, ex->Message);
}